package com.maixy.studyonlineapi.utils;


import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 *
 * @author HuangLinWei
 * @since 2019/4/24
 */
public class JacksonUtil {

    private static final Logger logger = LoggerFactory.getLogger(JacksonUtil.class);

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    static {
        OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    }

    public static ObjectMapper getInstance() {
        return OBJECT_MAPPER;
    }

    private JacksonUtil(){}

    /**
     * 将任意对象转换json
     *
     * @param obj
     * @return java.lang.String
     * @author HuangLinWei
     * @email linwei.huang@haku-mata.cn
     * @datetime 2018/5/18 14:30
     */
    public static String obj2json(Object obj) {
        try {
            return OBJECT_MAPPER.writeValueAsString(obj);
        } catch (Exception e) {
            logger.error("obj2json error", e);
        }
        return "";
    }

    /**
     * 将json转换成指定对象
     *
     * @param jsonStr
     * @param clazz
     * @return T
     * @author HuangLinWei
     * @email linwei.huang@haku-mata.cn
     * @datetime 2018/5/18 14:32
     */
    public static <T> T json2Bean(String jsonStr, Class<T> clazz) {
        try {
            return OBJECT_MAPPER.readValue(jsonStr, clazz);
        } catch (Exception e) {
            logger.error("json2Bean error", e);
        }
        return null;
    }

    /**
     * 将json转换成map
     *
     * @param jsonStr
     * @return java.util.Map<java.lang.String       ,       java.lang.Object>
     * @author HuangLinWei
     * @email linwei.huang@haku-mata.cn
     * @datetime 2018/5/18 14:32
     */
    public static <T> Map<String, Object> json2map(String jsonStr) {
        try {
            return OBJECT_MAPPER.readValue(jsonStr, Map.class);
        } catch (Exception e) {
            logger.error("json2map error", e);
        }
        return new HashMap<>();

    }


    /**
     * @param jsonArrayStr
     * @param clazz
     * @return java.util.List<T>
     * @author HuangLinWei
     * @email linwei.huang@haku-mata.cn
     * @datetime 2018/5/18 14:36
     */
    public static <T> List<T> json2list(String jsonArrayStr, Class<T> clazz) {
        List<T> result = new ArrayList<>();
        try {
            JavaType collectionType = getCollectionType(ArrayList.class, clazz);
            return OBJECT_MAPPER.readValue(jsonArrayStr, collectionType);
        } catch (Exception e) {
            logger.error("json2list error", e);
        }
        return result;
    }

    /**
     * 将 json 字符串转为 set 集合
     *
     * @param jsonArrayStr json 字符串
     * @param clazz 泛型
     * @return java.util.List<T>
     * @author HuangLinWei
     * @since 2019/8/21
     */
    public static <T> Set<T> jsonToSet(String jsonArrayStr, Class<T> clazz) {
        Set<T> result = new HashSet<>();
        try {
            JavaType collectionType = getCollectionType(HashSet.class, clazz);
            return OBJECT_MAPPER.readValue(jsonArrayStr, collectionType);
        } catch (Exception e) {
            logger.error("jsonToSet error", e);
        }
        return result;
    }

    /**
     * @param map
     * @param clazz
     * @return T
     * @author HuangLinWei
     * @email linwei.huang@haku-mata.cn
     * @datetime 2018/5/18 14:37
     */
    public static <T> T map2bean(Map map, Class<T> clazz) {
        return OBJECT_MAPPER.convertValue(map, clazz);
    }

    public static Map<String, Object> obj2map(Object o) {
        String json = obj2json(o);
        if (StringUtils.isNotBlank(json)) {
            return json2map(json);
        }
        return null;
    }

    /**
     * 获取泛型的Collection Type
     *
     * @param collectionClass 泛型的Collection
     * @param elementClasses 元素类
     * @return com.fasterxml.jackson.databind.JavaType
     * @author HuangLinWei
     * @since 2018/10/13
     */
    public static JavaType getCollectionType(Class<?> collectionClass, Class<?>... elementClasses) {
        return OBJECT_MAPPER.getTypeFactory().constructParametricType(collectionClass, elementClasses);
    }
}
